package com.ybox.gateway.captcha.utils;


import com.ybox.gateway.captcha.*;
import com.ybox.gateway.captcha.base.Captcha;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.util.Random;

/**
 * 图形验证码工具类
 *
 * @Author ych
 */
public class CaptchaUtil {
    private static final String SESSION_KEY = "captcha";
    private static final int DEFAULT_LEN = 4;  // 默认长度
    private static final int MAX_LEN = 8;  // 默认长度
    private static final int MIN_LEN = 0;  // 默认长度
    private static final int DEFAULT_WIDTH = 160;  // 默认宽度
    private static final int MAX_WIDTH = 300;  // 最大宽度
    private static final int MIN_WIDTH = 50;  // 最小宽度
    private static final int DEFAULT_HEIGHT = 60;  // 默认高度
    private static final int MAX_HEIGHT = 300;  // 最大高度
    private static final int MIN_HEIGHT = 50;  // 最小高度

    private static Random random = new Random();

    /**
     * 输出验证码
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        out(DEFAULT_LEN, request, response);
    }

    /**
     * 输出验证码
     *
     * @param len      长度
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(int len, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        out(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, request, response);
    }

    /**
     * 输出验证码
     *
     * @param width    宽度
     * @param height   高度
     * @param len      长度
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(int width, int height, int len, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        out(width, height, len, null, request, response);
    }

    /**
     * 输出验证码
     *
     * @param font     字体
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(Font font, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        out(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_LEN, font, request, response);
    }

    /**
     * 输出验证码
     *
     * @param len      长度
     * @param font     字体
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(int len, Font font, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        out(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, font, request, response);
    }

    /**
     * 输出验证码
     *
     * @param width    宽度
     * @param height   高度
     * @param len      长度
     * @param font     字体
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(int width, int height, int len, Font font, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        SpecCaptcha specCaptcha = new SpecCaptcha(width, height, len);
        if (font != null) {
            specCaptcha.setFont(font);
        }
        out(specCaptcha, request, response);
    }


    /**
     * 输出验证码
     *
     * @param captcha  Captcha
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void out(Captcha captcha, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        setHeader(response);
        request.getSession().setAttribute(SESSION_KEY, captcha.text().toLowerCase());
        captcha.out(response.getOutputStream());
    }

    /**
     * 验证验证码
     *
     * @param code    用户输入的验证码
     * @param request HttpServletRequest
     * @return 是否正确
     */
    public static boolean ver(String code, HttpServletRequest request) {
        if (code != null) {
            String captcha = (String) request.getSession().getAttribute(SESSION_KEY);
            return code.trim().toLowerCase().equals(captcha);
        }
        return false;
    }

    /**
     * 清除session中的验证码
     *
     * @param request HttpServletRequest
     */
    public static void clear(HttpServletRequest request) {
        request.getSession().removeAttribute(SESSION_KEY);
    }

    /**
     * 设置相应头
     *
     * @param response HttpServletResponse
     */
    public static void setHeader(HttpServletResponse response) {
        response.setContentType("image/gif");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
    }

    /**
     * 参数修正
     *
     * @param width  宽度
     * @param height 高度
     * @param len    长度
     */
    public static int[] correct(int width, int height, int len) {
        if (width < MIN_WIDTH || width > MAX_WIDTH) {
            width = DEFAULT_WIDTH;
        }
        if (height < MIN_HEIGHT || height > MAX_HEIGHT) {
            height = DEFAULT_HEIGHT;
        }
        if (len == MIN_LEN || MAX_LEN > 8) {
            len = DEFAULT_LEN;
        }
        return new int[]{width, height, len};
    }

    /**
     * 获取验证码
     *
     * @param captchaType 验证码类型 算数 字符 中文
     * @param imageType   图片类型 png gif
     * @param width       宽度
     * @param height      高度
     * @param len         长度
     * @return
     */
    public static Captcha getCaptcha(String captchaType, String imageType, int width, int height, int len) {
        Captcha captcha = null;
        int[] correct = correct(width, height, len);
        if ("math".equals(captchaType)) {
            captcha = new ArithmeticCaptcha(correct[0], correct[1], 2);
        } else if ("char".equals(captchaType) && "png".equals(imageType)) {
            captcha = new SpecCaptcha(correct[0], correct[1], correct[2]);
        } else if ("char".equals(captchaType) && "gif".equals(imageType)) {
            captcha = new GifCaptcha(correct[0], correct[1], correct[2]);
        } else if ("chineseChar".equals(captchaType) && "png".equals(imageType)) {
            captcha = new ChineseCaptcha(correct[0], correct[1], correct[2]);
        } else if ("chineseChar".equals(captchaType) && "gif".equals(imageType)) {
            captcha = new ChineseGifCaptcha(correct[0], correct[1], correct[2]);
        }
        return captcha;
    }


    /**
     * 未指定图片类型  随机生成
     *
     * @param captchaType 验证码类型 算数 字符 中文
     * @param width       宽度
     * @param height      高度
     * @param len         长度
     * @return
     */
    public static Captcha getCaptchaByRandomImageType(String captchaType, int width, int height, int len) {
        String[] imageTypes = {"png", "gif"};
        String imageType = imageTypes[random.nextInt(2)];
        return getCaptcha(captchaType, imageType, width, height, len);
    }


    /**
     * 未指定验证码类型  随机生成
     *
     * @param imageType 图片类型 png gif
     * @param width     宽度
     * @param height    高度
     * @param len       长度
     * @return
     */
    public static Captcha getCaptchaByRandomCodeType(String imageType, int width, int height, int len) {
        // 未指定图片类型  随机生成
        String[] captchaTypes = {"char", "chineseChar", "math"};
        String captchaType = captchaTypes[random.nextInt(3)];
        return getCaptcha(captchaType, imageType, width, height, len);
    }

    /**
     * 未指定图片类型和验证码类型  随机生成
     *
     * @param width  宽度
     * @param height 高度
     * @param len    长度
     * @return
     */
    public static Captcha getCaptchaByRandomImageTypeAndCodeType(int width, int height, int len) {
        String[] imageTypes = {"png", "gif"};
        String imageType = imageTypes[random.nextInt(2)];

        String[] captchaTypes = {"char", "chineseChar", "math"};
        String captchaType = captchaTypes[random.nextInt(3)];
        return getCaptcha(captchaType, imageType, width, height, len);
    }
}
